/*
 * @Author: Turump 
 * @Date: 2021-03-26 10:58:38 
 * @Last Modified by: Turump
 * @Last Modified time: 2021-09-15 14:19:47
 * 一些方法集合
 */

export enum Direction {
    Top = 1,
    Left = 2,
    Right = 3,
    Bottom = 4,
    LeftTop,
    RightTop,
    LeftBottom,
    RightBottom,
}

cc.macro.ENABLE_WEBGL_ANTIALIAS = true

export default class CocosHelper {
    /**
     * 以某个节点为目标，截取目标节点内容图片，需要添加group名为captureLayer才能正常工作
     * @param distNode 
     * @param width 
     * @param height 
     * @returns RenderTexture
     */
    static captureNodeSize(distNode: cc.Node, width: number, height: number, adjustZoomRatio: boolean = false): Promise<cc.RenderTexture> {
        return new Promise((resolve, reject) => {
            // if(CC_JSB && cc.sys.isMobile == false) {
            //     cc.warn("防止死机, 模拟器不截图");
            //     resolve(null);
            //     return;
            // }
            let cameraNode = distNode.getChildByName('cameraNode');
            if (!cameraNode) {
                cameraNode = new cc.Node('cameraNode');
                cameraNode.parent = distNode;
                cameraNode.x = 0;
                cameraNode.y = 0;
            }
            let camera = cameraNode.getComponent(cc.Camera);
            if (!camera) {
                camera = cameraNode.addComponent(cc.Camera);
                if (adjustZoomRatio) {
                    let ratio = Math.max(cc.visibleRect.width / width, cc.visibleRect.height / height)
                    camera.zoomRatio = ratio;
                }
            }
            let preGroug = distNode.group;
            distNode.group = "captureLayer";
            // 设置你想要的截图内容的 cullingMask
            camera.cullingMask = distNode["_cullingMask"];//0xffffffff;

            // 新建一个 RenderTexture，并且设置 camera 的 targetTexture 为新建的 RenderTexture，这样 camera 的内容将会渲染到新建的 RenderTexture 中。
            let texture = new cc.RenderTexture();
            // 初始化纹理大小，如果截图内容中不包含 Mask 组件，可以不用传递第三个参数
            texture.initWithSize(width, height, cc.game['_renderContext'].STENCIL_INDEX8);
            camera.targetTexture = texture;

            // 渲染一次摄像机，即更新一次内容到 RenderTexture 中
            let scaeY = distNode.scaleY;
            //distNode.scaleY = -1 * scaeY;
            camera.render(null);
            camera.enabled = false;
            //distNode.scaleY = scaeY;
            distNode.group = preGroug;
            resolve(texture);

        })
    }

    /**
     * 指定方向，获取节点在屏幕外的起点，用点出入场动画等
     */
    static getNodeOutScreenPosition(node: cc.Node, dir: Direction) {
        let curentPosition = node.convertToWorldSpaceAR(cc.Vec2.ZERO);

        let bottomRight = cc.v2(cc.visibleRect.width, 0);
        let topLeft = cc.v2(0, cc.visibleRect.height);

        let contentSize = node.getBoundingBoxToWorld().size;
        let bottomY = bottomRight.y - contentSize.height * (1 - node.getAnchorPoint().y) - 100
        let topY = topLeft.y + contentSize.height * (node.getAnchorPoint().y) + 100
        let leftX = topLeft.x - contentSize.width * (1 - node.getAnchorPoint().x) - 100
        let rightX = bottomRight.x + contentSize.width * node.getAnchorPoint().x + 100
        let endPosition: cc.Vec2;
        switch (dir) {
            case Direction.Bottom:
                endPosition = new cc.Vec2(curentPosition.x, bottomY);
                break;
            case Direction.Left:
                endPosition = new cc.Vec2(leftX, curentPosition.y);
                break;
            case Direction.Right:
                endPosition = new cc.Vec2(rightX, curentPosition.y);
                break;
            case Direction.Top:
                endPosition = new cc.Vec2(curentPosition.x, topY);
                break;
            case Direction.RightBottom:
                endPosition = cc.v2(rightX, bottomY);
                break;
            case Direction.LeftBottom:
                endPosition = cc.v2(leftX, bottomY);
                break;
            case Direction.LeftTop:
                endPosition = cc.v2(leftX, topY)
                break;
            case Direction.RightTop:
                endPosition = cc.v2(rightX, topY)
                break;
        }
        // let pt1 = node.convertToNodeSpaceAR(endPosition);
        let pt2 = node.parent.convertToWorldSpaceAR(cc.Vec2.ZERO);
        let pt3 = endPosition.sub(pt2);
        // endPosition = node.parent.convertToNodeSpaceAR(endPosition);
        return pt3;
    }

    /**
     * @returns 节点在新父节点下的坐标
     */
    static getPositionForNewParent(node: cc.Node, newParent: cc.Node) {
        let worltPt = node.convertToWorldSpaceAR(cc.Vec2.ZERO);
        let localPt = newParent.convertToNodeSpaceAR(worltPt);
        return localPt;
    }

    /**
     * 换父节点
     */
    static changeParent(node: cc.Node, newParent: cc.Node) {
        if (node == null || newParent == null) {
            cc.error("CococsHelper changeParent failed for null node");
            return;
        }
        let oldScale = this.getRealScaleToRoot(node);
        let localPt = this.getPositionForNewParent(node, newParent);
        node.parent = newParent;
        node.setPosition(localPt);
        node.scale = oldScale / this.getRealScaleToRoot(newParent);
    }

    /**
     * 嵌套查找满足条件的节点
     * @param _root 开始查找的节点
     * @param _fun 条件方法
     * @returns 
     */
    static findNode_if(_root: cc.Node, _fun: Function): cc.Node {
        let find: cc.Node = null;
        if (_root != null) {
            let flag = _fun(_root);
            if (flag) {
                find = _root;
            } else {
                let child = _root.children;
                for (let c of child) {
                    find = this.findNode_if(c, _fun);
                    if (find != null) {
                        break;
                    }
                }
            }
        }
        return find;
    }

    /**
     * 根据名字查找子节点
     * @param _root 
     * @param name 
     * @returns 
     */
    static findNode(_root: cc.Node = cc.director.getScene(), name: string): cc.Node {
        return CocosHelper.findNode_if(_root, function (_node: cc.Node) {
            return _node.name == name;
        });
    }

    /**
     * 一直向根溯源，找出真实缩放
     * @param node 
     */
    static getRealScaleToRoot(node: cc.Node) {
        let scale = 1;
        while (node) {
            scale *= node.scale;
            node = node.parent;
        }
        return scale;
    }

    static showHand(handNode: cc.Node, oneNode: cc.Node, twoNode: cc.Node, threeNode: cc.Node) {
        let nodePos1 = handNode.parent.convertToNodeSpaceAR(oneNode.convertToWorldSpaceAR(cc.v2(0, 0)));
        let nodePos2 = handNode.parent.convertToNodeSpaceAR(twoNode.convertToWorldSpaceAR(cc.v2(0, 0)));
        let nodePos3 = handNode.parent.convertToNodeSpaceAR(threeNode.convertToWorldSpaceAR(cc.v2(0, 0)));
        if (oneNode.name == twoNode.name) {
            let a2 = cc.moveTo(1.0, nodePos2);
            let a3 = cc.moveTo(1.0, nodePos3);
            handNode.runAction(cc.repeatForever(cc.sequence(cc.callFunc(() => {
                handNode.setPosition(nodePos1);
            }), a3, cc.callFunc(() => {
                handNode.setPosition(cc.v2(1000, 1000000));
            }), cc.delayTime(1.0))));
        } else {
            let a2 = cc.moveTo(1.0, nodePos2);
            let a3 = cc.moveTo(1.0, nodePos3);
            handNode.runAction(cc.repeatForever(cc.sequence(cc.callFunc(function () {
                handNode.setPosition(nodePos1);
            }), a2, a3, cc.callFunc(function () {
                handNode.setPosition(cc.v2(1000, 1000000));
            }), cc.delayTime(1.0))));
        }
    }

    static saveRenderTexurePic(rt: cc.RenderTexture, savePicName: string, data?) {
        data = data || rt.readPixels();
        for (let h = 0; h < rt.height / 2; ++h) {
            for (let w = 0; w < rt.width; ++w) {
                for (let i = 0; i < 4; ++i) {
                    let temp = data[(h * rt.width + w) * 4 + i];
                    data[(h * rt.width + w) * 4 + i] = data[((rt.height - 1 - h) * rt.width + w) * 4 + i];
                    data[((rt.height - 1 - h) * rt.width + w) * 4 + i] = temp;
                }
            }
        }
        if (CC_JSB) {
            let filePath = jsb.fileUtils.getWritablePath() + savePicName;
            let ret = jsb['saveImageData'](data, rt.width, rt.height, filePath);
            console.log(`CocosHelper saveRenderTexurePic at:${filePath} ret:${ret}`);
        }
    }

    static isPtInNode(node: cc.Node, ptWorld: cc.Vec2) {
        let ptLocal = node.parent.convertToNodeSpaceAR(ptWorld);
        let rect = node.getBoundingBox();
        return rect.contains(ptLocal);
    }

    static createSpriteNode(sf: cc.SpriteFrame) {
        let node = new cc.Node();
        let spr = node.addComponent(cc.Sprite);
        spr.spriteFrame = sf;
        return node;
    }

    static disableButton(e:cc.Event.EventTouch) {
        if(e == null)
            return;
        let node = e.target as cc.Node;
        if(!node)
            return;
        let btn = node.getComponent(cc.Button);
        btn && (btn.interactable = false);
    }
}